package com.zoe.onelink.business.mybatis.interceptor;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.defaults.DefaultSqlSession;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * <p>标题: 批量操作使用jdbc进行操作</p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2019</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: cxy
 * @date: 2019/3/12
 */
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Deprecated
public class BatchByJdbcInterceptor implements Interceptor {

    private static final String BATCH_METHOD_POSTFIX = "BatchByJdbc";
    private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    public BatchByJdbcInterceptor(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        int count = 0;
        // 获得SQL语句
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        if (!mappedStatement.getId().endsWith(BATCH_METHOD_POSTFIX)) {
            return invocation.proceed();
        }
        Object parameter = null;

        List<SqlParameterSource> sourceList = new ArrayList<>();
        Object execParam = null;
        if (invocation.getArgs().length > 1) {
            parameter = invocation.getArgs()[1];
            Map<String, Object> argsMap = parameter instanceof MapperMethod.ParamMap ? (MapperMethod.ParamMap) parameter : (DefaultSqlSession.StrictMap) parameter;
            List<?> list = (List<?>) argsMap.getOrDefault("list", Collections.emptyList());
            execParam = list;
            for (Object o : list) {
                SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(o);
                sourceList.add(parameterSource);
            }
        }
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        String sql = boundSql.getSql();
        if (sourceList.size() > 0) {
            SqlParameterSource[] sqlParameterSources = new SqlParameterSource[sourceList.size()];
            int[] updateCount;
            try {
                updateCount = this.namedParameterJdbcTemplate.batchUpdate(sql, sourceList.toArray(sqlParameterSources));
            } catch (Exception e) {
                String updateParamStr;
                Collection<?> collParam = (Collection) execParam;
                if (collParam.size() > 100) {
                    updateParamStr = "参数超过100个,已自动忽略";
                } else {
                    updateParamStr = JSON.toJSONString(execParam);
                }
                log.error("[JDBC批量操作失败] SQL: {} , Params: {}", sql, updateParamStr);
                throw e;
            }
            count = updateCount.length;
        }
        return count;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
